<script>
import App from './App'
import http from './common/request';
import * as msgType from './common/messageType';
import * as enums from './common/enums';
import * as wsApi from './common/wssocket';
import UNI_APP from '@/.env.js'

export default {
  data() {
    return {
      isInit: false, // 是否完成初始化
      isInBackGroup: false, // 是否在后台运行
      isExit: false, // 是否已退出
      audioTip: null,
      reconnecting: false, // 正在重连标志
      isPushModule: false // 是否勾选了unipush
    }
  },
  onLaunch() {
    this.$mountStore();
    // 检测是否打包了unipush模块
    this.checkPushModule();
    // 延迟1s，避免用户看到页面跳转
    this.closeSplashscreen(1000);
    // 加载系统配置
    this.configStore.loadConfig();
    this.closeSplashscreen(0);
  },
  onShow: function () {
    // console.log('uni.getStorageSync("loginInfo")', uni.getStorageSync("loginInfo"));
    // this.init();
    // 检查是否需要重连WebSocket
    this.isInBackGroup = false;
    if (this.isPushModule) {
      plus.push.clear();
    }
  },
  methods: {
    init() {
      this.reconnecting = false;
      this.isExit = false;
      // 加载数据
      return this.loadStore().then(() => {
        // 初始化websocket
        this.initWebSocket();
        this.reportCid();
        this.initUniPush();
        setTimeout(() => {
          this.$badge.refreshFriendBadge();
          this.$badge.refreshChatBadge();
        }, 1000)
        this.isInit = true;
        return Promise.resolve();
      }).catch((err) => {
        console.error('初始化失败:', err);
        this.isInit = true; // 即使失败也标记为已初始化，避免页面卡死
        return Promise.reject(err);
      });
    },
    initWebSocket() {
      let loginInfo = uni.getStorageSync("loginInfo")
      // uni.setClipboardData({
      // 	data: loginInfo // 要复制的文本内容
      // })
      wsApi.connect(UNI_APP.WS_URL, loginInfo.accessToken);
      wsApi.onConnect(() => {
        this.pullPrivateOfflineMessage(this.chatStore.privateMsgMaxId);
        this.pullSystemOfflineMessage(this.chatStore.privateMsgMaxId);
        // 重连成功提示
        if (this.reconnecting) {
          this.onReconnectWs();
        } else {
          // 加载离线消息
        }
      });
      wsApi.onMessage((cmd, msgInfo) => {
        if (cmd == 3) {
          // 私聊消息
          this.handlePrivateMessage(msgInfo);
          // 广播新消息通知
          uni.$emit('NEW_MESSAGE_RECEIVED');
        } else if (cmd == 5) {
          // 系统消息
          this.handleSystemMessage(msgInfo);
          // 广播新消息通知
          uni.$emit('NEW_MESSAGE_RECEIVED');
        }
      });
      wsApi.onClose((res) => {
        console.log("ws断开", res);
        // 重新连接
        this.reconnectWs();
      })
    },
    loadStore() {
      // 首先清理包含 undefined 的旧数据
      this.chatStore.cleanUndefinedData()

      return this.userStore.loadUser().then(() => {
        const promises = [];
        promises.push(this.friendStore.loadFriend());
        promises.push(this.chatStore.loadChat());
        promises.push(this.configStore.loadConfig());
        return Promise.all(promises);
      })
    },
    unloadStore() {
      this.friendStore.clear();
      this.chatStore.clear();
      this.userStore.clear();
    },
    pullPrivateOfflineMessage(minId) {
      this.chatStore.setLoadingPrivateMsg(true)
      http({
        url: "/message/private/pullOfflineMessage?minId=" + minId,
        method: 'GET'
      }).catch(() => {
        this.chatStore.setLoadingPrivateMsg(false)
      })
    },
    pullSystemOfflineMessage(minSeqNo) {
      this.chatStore.setLoadingSystemMsg(true)
      this.$http({
        url: "/message/system/pullOfflineMessage?minSeqNo=" + minSeqNo,
        method: 'GET'
      }).catch(() => {
        this.chatStore.setLoadingSystemMsg(false)
      })
    },
    handlePrivateMessage(msg) {
      // 标记这条消息是不是自己发的
      msg.selfSend = msg.sendId == this.userStore.userInfo.id;
      // 好友id
      let friendId = msg.selfSend ? msg.recvId : msg.sendId;
      // 会话信息
      let chatInfo = {
        type: 'PRIVATE',
        targetId: friendId
      }
      // 消息加载标志
      if (msg.type == enums.MESSAGE_TYPE.LOADING) {
        this.chatStore.setLoadingPrivateMsg(JSON.parse(msg.content))
        return;
      }
      // 消息已读处理，清空已读数量
      if (msg.type == enums.MESSAGE_TYPE.READED) {
        this.chatStore.resetUnreadCount(chatInfo)
        return;
      }
      // 消息回执处理,改消息状态为已读
      if (msg.type == enums.MESSAGE_TYPE.RECEIPT) {
        this.chatStore.readedMessage({
          friendId: msg.sendId
        })
        return;
      }
      // 消息撤回
      if (msg.type == enums.MESSAGE_TYPE.RECALL) {
        this.chatStore.recallMessage(msg, chatInfo);
        return;
      }
      // 好友申请
      if (msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPLY) {
        this.friendStore.addRequest(JSON.parse(msg.content))
        return;
      }
      // 好友申请被同意、拒绝、撤回
      if (msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPROVE ||
        msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_REJECT ||
        msg.type == enums.MESSAGE_TYPE.FRIEND_REQ_RECALL) {
        this.friendStore.removeRequest(JSON.parse(msg.content).id)
        return;
      }
      // 新增好友
      if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_NEW) {
        this.friendStore.addFriend(JSON.parse(msg.content));
        return;
      }
      // 删除好友
      if (msg.type == this.$enums.MESSAGE_TYPE.FRIEND_DEL) {
        this.friendStore.removeFriend(friendId);
        return;
      }
      // 消息插入
      let friend = this.loadFriendInfo(friendId);
      this.insertPrivateMessage(friend, msg);
    },
    insertPrivateMessage(friend, msg) {
      // 单人视频信令
      if (msgType.isRtcPrivate(msg.type)) {
        // #ifdef MP-WEIXIN
        // 小程序不支持音视频
        return;
        // #endif
        // 被呼叫，弹出视频页面
        let delayTime = 100;
        if (msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE ||
          msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO) {
          let mode = msg.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ? "video" : "voice";
          let pages = getCurrentPages();
          let curPage = pages[pages.length - 1].route;
          if (curPage != "pages/chat/chat-private-video") {
            const friendInfo = encodeURIComponent(JSON.stringify(friend));
            uni.navigateTo({
              url: `/pages/chat/chat-private-video?mode=${mode}&friend=${friendInfo}&isHost=false`
            })
            this.createNotifyMessage(friend.showNickName, msg);
            delayTime = 500;
          }
        }
        setTimeout(() => {
          uni.$emit('WS_RTC_PRIVATE', msg);
        }, delayTime)
        return;
      }
      // 插入消息
      if (msgType.isNormal(msg.type) || msgType.isTip(msg.type) || msgType.isAction(msg.type)) {
        let chatInfo = {
          type: 'PRIVATE',
          targetId: friend.id,
          showName: friend.showNickName,
          headImage: friend.headImage
        };
        // 打开会话
        this.chatStore.openChat(chatInfo);
        // 插入消息
        this.chatStore.insertMessage(msg, chatInfo);
        // 弹出通知栏消息
        this.createNotifyMessage(friend.showNickName, msg);
        // 播放提示音
        this.playAudioTip();
      }
    },
    handleSystemMessage(msg) {
      // 消息加载标志
      if (msg.type == this.$enums.MESSAGE_TYPE.LOADING) {
        this.chatStore.setLoadingSystemMsg(JSON.parse(msg.content));
        return;
      }
      // 消息已读处理 
      if (msg.type == enums.MESSAGE_TYPE.READED) {
        // 我已读对方的消息，清空已读数量
        let chatInfo = {
          type: 'SYSTEM',
          targetId: 0
        }
        this.chatStore.resetUnreadCount(chatInfo)
        return;
      }
      if (msg.type == enums.MESSAGE_TYPE.USER_BANNED) {
        // 用户被封禁
        wsApi.close(3099);
        uni.showModal({
          content: '您的账号已被管理员封禁，原因:' + msg.content,
          showCancel: false,
        })
        return;
      }
      if (msg.type == enums.MESSAGE_TYPE.USER_UNREG) {
        // 用户账号已注销
        wsApi.close(3099);
        uni.showModal({
          content: '您的账号已注销',
          showCancel: false,
        })
        return;
      }
      // 插入消息
      this.insertSystemMessage(msg);
    },
    insertSystemMessage(msg) {
      let headImage = '/static/image/chat_system.png';
      let chatInfo = {
        type: 'SYSTEM',
        targetId: 0,
        showName: "系统通知",
        headImage: headImage
      };
      // 打开会话
      this.chatStore.openChat(chatInfo);
      // 插入消息
      this.chatStore.insertMessage(msg, chatInfo);
    },
    loadFriendInfo(id, callback) {
      let friend = this.friendStore.findFriend(id);
      if (!friend) {
        friend = {
          id: id,
          showNickName: "未知用户",
          headImage: ""
        }
      }
      return friend;
    },
    exit() {
      console.log("exit");
      this.isExit = true;
      wsApi.close(3099);

      // 清空所有会话和状态
      console.log("调用方法:清空所有会话和状态");
      this.chatStore.clear();
      this.friendStore.clear();
      this.userStore.clear();

      // 清空存储
      uni.removeStorageSync("loginInfo");
      uni.removeStorageSync("userId");

      // 不跳转到不存在的登录页面，而是重新初始化
      // 重新加载页面或显示错误提示
      try {
        // 尝试重新初始化应用
        this.init();
      } catch (error) {
        console.error("重新初始化失败:", error);
        // 如果重新初始化失败，显示错误提示
        uni.showModal({
          title: '提示',
          content: '应用初始化失败，请刷新页面重试',
          showCancel: false,
          success: () => {
            // 刷新当前页面
            location.reload();
          }
        });
      }

      this.unloadStore();
    },
    playAudioTip() {
      // 音频播放无法成功
      // this.audioTip = uni.createInnerAudioContext();
      // this.audioTip.src =  "/static/audio/tip.wav";
      // this.audioTip.play();
    },
    refreshToken(loginInfo) {
      return new Promise((resolve, reject) => {
        if (!loginInfo || !loginInfo.refreshToken) {
          reject();
          return;
        }
        http({
          url: '/refreshToken',
          method: 'PUT',
          header: {
            refreshToken: loginInfo.refreshToken
          }
        }).then((newLoginInfo) => {
          uni.setStorageSync("loginInfo", newLoginInfo)
          resolve()
        }).catch((e) => {
          reject(e)
        })
      })
    },
    reconnectWs() {
      // 已退出则不再重连
      // if (this.isExit) {
      // 	return;
      // }
      // 记录标志
      this.reconnecting = true;
      // 重新加载一次个人信息，目的是为了保证网络已经正常且token有效
      this.userStore.loadUser().then((userInfo) => {
        // 静默重连，不显示提示
        console.log('连接已断开，尝试重新连接...');

        // 重新连接
        let loginInfo = uni.getStorageSync("loginInfo")
        wsApi.reconnect(UNI_APP.WS_URL, loginInfo.accessToken);
      }).catch(() => {
        // 5s后重试
        setTimeout(() => {
          this.reconnectWs();
        }, 5000)
      })
    },
    onReconnectWs() {
      this.reconnecting = false;
      // 重新加载好友
      const promises = [];
      promises.push(this.friendStore.loadFriend());

      // 确保聊天数据加载
      promises.push(this.chatStore.loadChat().then(() => {
        // 重新加载离线消息，使用静默模式
        return this.chatStore.fetchChats(true);
      }));

      Promise.all(promises).then(() => {
        // 不显示重连提示，静默处理
        console.log("WebSocket已重新连接");

        // 广播WebSocket重连事件，让所有页面知道已重连
        uni.$emit('WS_RECONNECTED');

        // 更新角标
        this.$badge.refreshFriendBadge();
        this.$badge.refreshChatBadge();
      }).catch((e) => {
        // 不要自动退出到登录页
        console.log("重连数据加载失败:", e);
        // 继续尝试重连
        setTimeout(() => {
          this.reconnectWs();
        }, 5000);
      })
    },
    createNotifyMessage(title, msg) {
      if (!this.isPushModule) {
        return
      }
      const content = this.createNotifyContent(msg)
      // 仅在后台时弹出提示
      if (!content || !this.isInBackGroup) {
        return;
      }
      const options = {
        cover: true,
        sound: 'system',
        title: title,
        //icon: 'static/tarbar/chat_active.png'
      };
      plus.push.createMessage(content, {}, options);
    },
    createNotifyContent(msg) {
      let content = msg.content;
      switch (msg.type) {
        case enums.MESSAGE_TYPE.IMAGE:
          content = "[图片]";
          break;
        case enums.MESSAGE_TYPE.VIDEO:
          content = "[视频]";
          break;
        case enums.MESSAGE_TYPE.FILE:
          content = "[文件]";
          break;
        case enums.MESSAGE_TYPE.AUDIO:
          content = "[语音]";
          break;
        case enums.MESSAGE_TYPE.RTC_SETUP_VOICE:
        case enums.MESSAGE_TYPE.RTC_SETUP_VIDEO:
          content = "邀请您进行通话";
          break;
      }
      return content;
    },
    initUniPush() {
      if (!this.isPushModule) {
        return
      }
      plus.push.setAutoNotification(true);
      plus.push.clear();
      const clientInfo = plus.push.getClientInfo();
      plus.push.addEventListener('click', (message) => {
        const msgInfo = message.payload;
        this.onClickNotifyMessage(msgInfo);
      });
    },
    onClickNotifyMessage(msgInfo) {
      if (msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VIDEO ||
        msgInfo.type == enums.MESSAGE_TYPE.RTC_SETUP_VOICE) {
        this.$http({
          url: "/webrtc/private/info?uid=" + msgInfo.sendId,
          method: 'GET'
        }).then((rtcInfo) => {
          if (!rtcInfo.isChating) {
            return uni.showToast({
              title: '通话已结束',
              icon: 'none'
            })
          }
          // 进入被呼叫页面
          setTimeout(() => this.handlePrivateMessage(msgInfo), 500)
        })
      } else if (msgInfo.type == enums.MESSAGE_TYPE.FRIEND_REQ_APPLY) {
        // 好友验证
        this.onFriendRequestApplyNotify(msgInfo);
      }
    },
    onFriendRequestApplyNotify(msgInfo) {
      if (!this.isInit) {
        // 等待初始化完成再处理
        setTimeout(() => this.onFriendRequestApplyNotify(msgInfo), 1000);
        return;
      }
      // 跳转到验证页面
      let request = JSON.parse(msgInfo.content);
      if (!this.friendStore.isInSendRequest(request.sendId)) {
        uni.showToast({
          title: "该请求已被处理或撤销",
          icon: 'none'
        })
        return;
      }
      uni.navigateTo({
        url: `/pages/common/user-info?id=${request.sendId}&requestId=${request.id}`
      })
    },
    reportCid() {
      // APP需要上报cid，用于离线推送
      if (!this.isPushModule) {
        return
      }
      const clientInfo = plus.push.getClientInfo();
      const cid = clientInfo.clientid;
      if (cid && cid != "null") {
        console.log("cid:", cid)
        // 上报cid
        http({
          url: '/user/reportCid?cid=' + cid,
          method: 'POST'
        })
      } else {
        // 有时cid会拿不到,1s后重试
        setTimeout(() => this.reportCid(), 1000);
      }
    },
    removeCid() {
      if (!this.isPushModule) {
        return
      }
      http({
        url: '/user/removeCid',
        method: 'DELETE'
      })
    },
    closeSplashscreen(delay) {
      // #ifdef APP-PLUS
      // 关闭开机动画
      setTimeout(() => {
        plus.navigator.closeSplashscreen()
      }, delay)
      // #endif
    },
    checkPushModule() {
      // #ifdef APP-PLUS
      if (plus && plus.push) {
        plus.runtime.getProperty(plus.runtime.appid, (info) => {
          this.isPushModule = info.features.includes('push') || info.features.includes('Push');
        })
      }
      // #endif
    }
  },
  onHide() {
    this.isInBackGroup = true;
  }
}
</script>

<style lang="scss">
@import "@/uni_modules/uview-plus/index.scss";
@import "@/im.scss";
@import url("./static/icon/iconfont.css");

// #ifdef H5
uni-page-head {
  display: none; // h5浏览器本身就有标题
}

// #endif

.tab-page {
  display: flex;
  flex-direction: column;
  color: $im-text-color;
  font-size: $im-font-size;
  font-family: $font-family;
  background-color: $im-bg;
}

.page {
  position: relative;
  // #ifdef H5
  height: calc(100vh); // app平台还要减去顶部手机状态栏高度
  top: $im-nav-bar-height;
  // #endif
  // #ifndef H5
  height: calc(
    100vh - var(--status-bar-height)
  ); // app平台还要减去顶部手机状态栏高度
  top: calc($im-nav-bar-height + var(--status-bar-height));
  // #endif
  color: $im-text-color;
  background-color: $im-bg;
  font-size: $im-font-size;
  font-family: $font-family;
}

view,
scroll-view,
swiper,
swiper-item,
cover-view,
cover-image,
icon,
text,
rich-text,
progress,
button,
checkbox,
form,
input,
label,
radio,
slider,
switch,
textarea,
navigator,
audio,
camera,
image,
video {
  box-sizing: border-box;
}

image {
  display: block;
}
</style>